package com.ifar.audiosdk.activity

import android.os.Handler
import android.view.LayoutInflater
import android.view.View
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import com.alibaba.android.arouter.facade.annotation.Route
import com.google.gson.Gson
import com.ifar.audiosdk.R
import com.ifar.audiosdk.api.IfarWebSocketManager
import com.ifar.audiosdk.base.EngineBaseActivity
import com.ifar.audiosdk.common.IfarConfig
import com.ifar.audiosdk.common.IfarEventBusTag
import com.ifar.audiosdk.common.entity.IfarWebSocketEntity
import com.ifar.audiosdk.common.entity.UserInfoEntity
import com.ifar.audiosdk.model.main.adapter.UserListAdapter
import com.ifar.audiosdk.model.main.enum.UserStatus
import com.ifar.audiosdk.model.main.handle.CallHandle
import com.ifar.audiosdk.model.main.model.UserCallingState
import com.ifar.audiosdk.model.main.model.UserListEntityItem
import com.ifar.audiosdk.model.main.viewmodel.MainViewModel
import com.ifar.audiosdk.utils.ARouterHandle
import com.ifar.audiosdk.utils.GlassHandle
import com.ifar.audiosdk.utils.showToast
import com.llvision.glass3.platform.LLVisionGlass3SDK
import com.orhanobut.logger.Logger
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.glass_screen.view.*
import org.simple.eventbus.EventBus
import org.simple.eventbus.Subscriber
import org.simple.eventbus.ThreadMode

@Route(path = "/app/MainActivity")
class MainActivity : EngineBaseActivity<MainViewModel>(), IfarWebSocketManager.WsListener {
    private lateinit var userListAdapter: UserListAdapter
    private lateinit var vGlass: View
    private val data = mutableListOf<UserListEntityItem>()
    private var connectNum = 0          //websocket连接次数
    private var connectState = 0        //0未连接1连接2正在连接
    private val whatHeart = 0x001
    private val mGson = Gson()
    private var mHandle = Handler {
        when (it.what) {
            whatHeart -> sendHeart()
        }
        false
    }

    override fun getLayoutResId(): Int = R.layout.activity_main

    override fun initView() {
        mViewModel.getUserList()

        userListAdapter = UserListAdapter(data)
        rvUserList.layoutManager = LinearLayoutManager(mContext)
        rvUserList.adapter = userListAdapter
        userListAdapter.setOnItemClickListener { adapter, view, position ->
            val otherInfo = data[position]
            if (otherInfo.is_signin != "1") {
                return@setOnItemClickListener
            }
            CallHandle.updateStatusParam = UserStatus.CALL_OUT
            CallHandle.otherUserInfo = UserInfoEntity(
                otherInfo.id, otherInfo.nickname, otherInfo.avatar, otherInfo.permission
            )
            mViewModel.checkUserCallState(otherInfo.id)
        }

        vGlass = LayoutInflater.from(this).inflate(R.layout.glass_screen, null)
    }

    override fun initData() {
        connectState = 2
        mHandle.post(jobConnect)
    }

    override fun startObserve() {
        mViewModel.apply {
            apiGetUserListSuccess.observe(this@MainActivity) {
                data.clear()
                data.addAll(it)
                userListAdapter.notifyDataSetChanged()
            }

            apiUpdateUsersCallState.observe(this@MainActivity) {
                IfarConfig.channel_id = it.channel_id
                when (CallHandle.updateStatusParam) {
                    UserStatus.CALLING -> {
                        IfarWebSocketManager.requestCallConnect(
                            CallHandle.otherUserInfo.id, CallHandle.otherUserInfo.name
                        )
                        ARouterHandle.toCall(it.channel_id, it.agora_token)
                    }
                    UserStatus.REQUEST_HANGUP -> {
                        IfarWebSocketManager.requestCallAnswerHangup(
                            CallHandle.otherUserInfo.id, CallHandle.otherUserInfo.name
                        )
                    }
                    UserStatus.CALLING_HANGUP -> {
                        IfarWebSocketManager.leaveChannel()
                    }
                    UserStatus.CALL_OUT -> {
                        IfarWebSocketManager.requestCallOffer(
                            CallHandle.otherUserInfo.id, CallHandle.otherUserInfo.name
                        )
                        ARouterHandle.toCallOut(
                            CallHandle.otherUserInfo.avatar,
                            CallHandle.otherUserInfo.permission,
                            CallHandle.otherUserInfo.name,
                            CallHandle.otherUserInfo.id
                        )
                    }

                    else -> {
                    }
                }
            }

            apiCheckUserCallState.observe(this@MainActivity, Observer {
                val (callState, has_camera, has_mike, userID) = it[0]
                if (has_camera == "0" && has_mike == "0") {
                    Logger.e("对方没有摄像头和麦克风，无法视频通话！")
                    return@Observer
                }
                when (callState) {
                    "callin" -> {

                    }
                    "callout" -> {
                        updateUsersCallState(getUserId("calling"), "")
                    }
                    "idle" -> {
                        if (CallHandle.updateStatusParam == UserStatus.CALL_OUT) {
                            val otherUserInfo = CallHandle.otherUserInfo
                            val userIds = mutableListOf<UserCallingState>()
                            userIds.add(UserCallingState("callout", IfarConfig.id))
                            userIds.add(UserCallingState("callin", otherUserInfo.id))
                            updateUsersCallState(mGson.toJson(userIds), "")
                        }
                    }
                }
            })

            apiError.observe(this@MainActivity) {
                showToast(it)
            }
        }
    }

    private fun wxConnectSuccess() {
        connectNum = 0
        sendHeart()
    }

    private fun wxConnectFail() {
        Logger.e("wxConnectFail$connectNum")
        mHandle.removeMessages(whatHeart)
        if (connectNum < 5 && connectState == 0) {
            connectState = 2
            connectNum++
            mHandle.postDelayed(jobConnect, 5 * 1000)
        } else if (connectNum >= 5) {
            showToast("连接服务器失败，请重新登录。")
            ARouterHandle.toLogin()
            // TODO: 2021-03-19 退出登录
            finish()
        }
    }

    /**连接socket*/
    private val jobConnect = Runnable {
        IfarWebSocketManager.connect(this@MainActivity)
    }


    /**发送心跳*/
    private fun sendHeart() {
        IfarWebSocketManager.requestHeart()
        mHandle.sendEmptyMessageDelayed(whatHeart, 5 * 1000)
    }

    override fun wsOpen() {
        mHandle.removeCallbacks(jobConnect)
        connectState = 1
        wxConnectSuccess()
        IfarWebSocketManager.setUserAtts()              //修改pid
    }

    override fun wsClose() {
        connectState = 0
        wxConnectFail()
    }

    override fun wsMessage(msg: String) {
        Logger.e("---------------$msg")
        try {
            val (fromId, fromName, toID, toName, companyID, channelID, mFlag, sFlag, avatar, msgData) =
                mGson.fromJson(msg, IfarWebSocketEntity::class.java)
            when (mFlag) {
                "Login" -> {                            //异地登录
                    showToast("您的账号在另一设备上登录")
                    ARouterHandle.toLogin()// TODO: 2021-03-19 退出登录
                    finish()
                }
                "Home" -> {
                    when (sFlag) {
                        "UpdateUserList" ->             //更新用户列表
                            EventBus.getDefault().post("", IfarEventBusTag.UPDATE_LIST)
                    }
                }
                "CallAnswer" -> {
                    when (sFlag) {
                        "Connect" -> {                  //对方接通
                            EventBus.getDefault().post("", IfarEventBusTag.CALL_IN_OTHER_HANGUP)
                            CallHandle.updateStatusParam = UserStatus.CALLING
                            mViewModel.updateUsersCallState(getUserId("calling"), channelID)
                        }
                        "Hangup" -> {                   //对方挂断
                            CallHandle.otherUserInfo = UserInfoEntity(id = fromId, name = fromName)
                            CallHandle.updateStatusParam = UserStatus.REQUEST_HANGUP
                            mViewModel.updateUsersCallState(getUserId("hangup"), channelID)
                            EventBus.getDefault().post("", IfarEventBusTag.CALL_IN_OTHER_HANGUP)
                        }
                    }
                }
                "CallOffer" -> {
                    when (sFlag) {
                        "Request" -> {                  //对方拨打请求
                            ARouterHandle.toCallIn(
                                avatar, msgData.permission, fromName, fromId, channelID
                            )
                        }
                    }
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun getUserId(callState: String): String {
        val userIds = mutableListOf<UserCallingState>()
        userIds.add(UserCallingState(callState, IfarConfig.id))
        return mGson.toJson(userIds)
    }

    override fun initGlass() {
        GlassHandle.initGlass(this, vGlass)
    }

    override fun onDestroy() {
        if (LLVisionGlass3SDK.getInstance().isServiceConnected) {
            LLVisionGlass3SDK.getInstance().destroy()
        }
        super.onDestroy()
    }

    @Subscriber(tag = IfarEventBusTag.CALL_IN_HANGUP, mode = ThreadMode.MAIN)
    fun callInHangup(entity: UserInfoEntity) {
        CallHandle.otherUserInfo = entity
        CallHandle.updateStatusParam = UserStatus.REQUEST_HANGUP
        mViewModel.updateUsersCallState(getUserId("hangup"), "")
    }

    @Subscriber(tag = IfarEventBusTag.UPDATE_LIST, mode = ThreadMode.MAIN)
    fun updateList(string: String) {
        mViewModel.getUserList()
    }

    @Subscriber(tag = IfarEventBusTag.CALL_IN_ACCEPT, mode = ThreadMode.MAIN)
    fun callInAccept(entity: UserInfoEntity) {
        CallHandle.otherUserInfo = entity
        CallHandle.updateStatusParam = UserStatus.CALLING
        mViewModel.checkUserCallState(entity.id)
    }

    @Subscriber(tag = IfarEventBusTag.NET_WORK_CHANGE, mode = ThreadMode.MAIN)
    fun netWorkChange(string: String) {
        wxConnectFail()
    }

    @Subscriber(tag = IfarEventBusTag.CALLING_HANGUP, mode = ThreadMode.MAIN)
    fun callingHangup(string: String) {
        CallHandle.updateStatusParam = UserStatus.CALLING_HANGUP
        mViewModel.updateUsersCallState(getUserId("hangup"), "")
    }

    @Subscriber(tag = IfarEventBusTag.OPEN_GLASS_CAMERA, mode = ThreadMode.MAIN)
    fun openGlassView(string: String) {
        vGlass.tvTime.visibility = View.GONE
    }

    @Subscriber(tag = IfarEventBusTag.CLOSE_GLASS_CAMERA, mode = ThreadMode.MAIN)
    fun closeGlassView(string: String) {
        vGlass.tvTime.setBackgroundColor(getColor(R.color.black))
        vGlass.tvTime.visibility = View.VISIBLE
    }

    override fun deInitUIandEvent() {}


}